# # 课后作业
# - 什么是迭代器?什么是生成器?两者有什么区别?
#迭代器：惰性返回数据；
# 生成器：惰性返回数据，提供额外功能，实现程序暂停；
# 都同样提供了惰性返回的功能, 迭代器侧重于提供**数据**的惰性返回功能, 生成器侧重于**指令**的惰性返回功能
#
# - 协程的实现原理.
# 在生成器的基础上，提供传递值的功能，调用send之前需要调用next进行预激活；

# - `asyncio`实现原理
# 异步IO,实现原理:   维护一个事件对列，循环访问事件来完成异步；
#
# - 用协程实现一个计算平均数的函数


# # 利用yield，计算平均数，协程，计算平均数
# def coro_avg():
#     total=0
#     length=0
#     while True:
#         try:
#             value=yield total/length
#         except ZeroDivisionError:
#             value=yield 0
#
#         total+=value
#         length+=1
#
# my_avg=coro_avg()
# print(next(my_avg))#预激
# print(my_avg.send(3))#可以无限调用，计算平均数
# print(my_avg.send(4))#可以无限调用，计算平均数
# 0
# 3.0
# 3.5

#
#
# - 编写一个`asyncio`异步程序

# 异步I/O!!!!!!!!!~~~~~~02~~~~~
# async io异步io
import asyncio,time
class Response:
    status=200

async def sim_request(index):#模拟发送请求的函数
    print("模拟发送请求index： ",index)
    response=Response()
    # time.sleep(1)#模拟网络延迟
    # 当前是单线程运行的, 如果调用的是time.sleep(1), 那么这个线程会被阻塞
    # 当前线程被阻塞之后, 不会让渡cpu资源, 异步的效率就不会体现


    await asyncio.sleep(1)#让步，
    print("request index ",index,"status code:",response.status)
    return response.status

#获得消息对列，开始轮询实现这个任务
loop=asyncio.get_event_loop()
# 包装任务
task_arr=[]
for i in range(5):
    task_arr.append(sim_request(i))

# 循环访问事件来完成异步的消息维护
# loop.run_until_complete(asyncio.wait(task_arr))
res=loop.run_until_complete(asyncio.gather(*task_arr))
print(res)#[200, 200, 200, 200, 200]

loop.close() #关闭事件循环
#
#
# - 扩展: 了解`aiohttp`异步请求网址
# https://docs.aiohttp.org/en/stable/